home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / truffles - display mgr. / sprocket / sources / dialogutils.cp < prev    next >
Encoding:
Text File  |  1996-01-01  |  9.6 KB  |  386 lines

  1. /*
  2.     File:        DialogUtils.cp
  3.  
  4.     Contains:    Auto-sized error alert mechanism and ModalFilterProcs
  5.                 which correctly handle events.
  6.                 
  7.     Written by: Dave Falkenburg
  8.  
  9.     Copyright:    © 1993-1995 by Dave Falkenburg, all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.      
  13.          <8>     1/20/95    DRF        Gary Powell is a bug finding god. Fix an unitialized variable
  14.                                     problem in ErrorAlert.
  15.          <7>      1/3/95    DRF        Gave UPPs better names. Also moved StandardCloseDocument to
  16.                                     Document.h.
  17.          <6>    11/23/94    DRF        Add ToggleCheckBox, a nice little dialog item utility.
  18.          <5>    11/16/94    DRF        Added explicit #include <SegLoad.h> for latest universal
  19.                                     headers. Also added cast to keep MPW CFront happier.
  20.          <4>    11/16/94    DRF        Add StdFilterProc for THINK C.
  21.          <3>     9/27/94    DRF         AppLib.h is now Sprocket.h
  22.          <2>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  23.  */
  24.  
  25. #include "Sprocket.h"
  26.  
  27. #include <Fonts.h>
  28. #include <Resources.h>
  29. #include <TextUtils.h>
  30. #include <Threads.h>        //    For YieldToAnyThread()
  31. #include <StandardFile.h>    //    For ModalFilterYDProcPtr
  32. #include <SegLoad.h>        //    For ExitToShell()
  33.  
  34. //    Some types which should probably be defined in <Dialogs.h>
  35. //    NOTE: These must be aligned on 2-byte boundaries
  36.  
  37. #if PRAGMA_ALIGN_SUPPORTED
  38. #pragma    push
  39. #pragma options align=mac68k
  40. #endif
  41.  
  42. struct DialogItem
  43.     {
  44.     long    usedByDialogManager;
  45.     Rect    boundsRect;
  46.     char    type;
  47.     char    length;
  48.     };
  49.  
  50. struct DialogItemList            //    a.k.a. a 'DITL'
  51.     {
  52.     short        count;
  53.     DialogItem    firstItem[1];
  54.     };
  55.  
  56. //    Restore default alignment
  57.  
  58. #if PRAGMA_ALIGN_SUPPORTED
  59. #pragma pop
  60. #endif
  61.  
  62.  
  63. typedef    DialogItem        *DialogItemPtr;
  64. typedef    DialogItemList    **DialogItemListHandle;
  65. typedef    DialogTemplate    **DialogTemplateHandle;
  66.  
  67. /*
  68. #ifndef    powerc
  69. #ifdef    __SC__
  70.  
  71. extern pascal OSErr GetStdFilterProc(ModalFilterUPP *theProc)
  72.  THREEWORDINLINE(0x303C, 0x0203, 0xAA68);
  73.  
  74. pascal Boolean
  75. StdFilterProc(DialogPtr theDialog, EventRecord* anEvent, short* itemHit)
  76.     {
  77.     ModalFilterUPP    filterUPP;
  78.  
  79.     //    Dialogs.h
  80.     
  81.     (void) GetStdFilterProc(&filterUPP);
  82.  
  83.     return    CallModalFilterProc(filterUPP,theDialog,anEvent,itemHit);
  84.     }
  85.  
  86. #endif
  87. #endif
  88. */
  89.  
  90. //    private function Prototypes
  91.  
  92. pascal Boolean    StandardDialogFilterProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
  93. static    pascal Boolean    StandardDialogFilterYDProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit, void * yourData);
  94. static    pascal Boolean    StandardCloseDialogFilterProc(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
  95. static    Boolean            FilterProcCommon(DialogRef theDialog, EventRecord * anEvent, short * itemHit);
  96.  
  97.  
  98.  
  99. ///////////////////////////////////////////////////////////
  100. //
  101. //    StandardAlert
  102. //
  103. //    An alternative to Alert() which uses the extended
  104. //    Dialog Manager capabilities.
  105. //
  106. //    I’m not sure we really need this call, but it seems
  107. //    to do the trick just fine.
  108.  
  109. short
  110. StandardAlert(    short dlogID,
  111.                 short defaultItem,                /* = ok */
  112.                 short cancelItem,                /* = 0 */
  113.                 ModalFilterUPP customFilterUPP    /* = nil */)
  114.     {
  115.     DialogRef        theDialog;
  116.     short            itemHit = 0;
  117.     ModalFilterUPP    filterToUse;
  118.     
  119.     TWindow::EnterModalState();
  120.  
  121.     theDialog = GetNewDialog(dlogID,nil,(WindowRef) -1);
  122.     if (defaultItem)
  123.         SetDialogDefaultItem(theDialog,defaultItem);
  124.     if (cancelItem)
  125.         SetDialogCancelItem(theDialog,cancelItem);
  126.  
  127.     if (customFilterUPP)
  128.         filterToUse = customFilterUPP;
  129.     else
  130.         filterToUse = StandardDialogFilterUPP;
  131.  
  132.     do
  133.         ModalDialog(filterToUse,&itemHit);
  134.     while (itemHit == 0);
  135.     
  136.     DisposeDialog(theDialog);
  137.  
  138.     TWindow::ExitModalState();
  139.  
  140.     return itemHit;
  141.     }
  142.  
  143.  
  144. ///////////////////////////////////////////////////////////
  145. //
  146. //    ErrorAlert
  147. //
  148. //    A nice error reporting routine which presents an
  149. //    auto-sized alert box containing the supplied text.
  150. //
  151. //    NOTE:    This routine ASSUMES the following 'DITL'
  152. //            structure:
  153. //
  154. //            item #1 : an “OK” button
  155. //            item #2 : a static text item, somewhere above #1
  156. //
  157. //    NOTE:    We probably need to worry more about low
  158. //            memory conditions-- this can probably
  159. //            be handled by a custom GrowZoneProc and
  160. //            reserve memory area large enough to hold
  161. //            all the space we’d need.
  162. //
  163.  
  164. void
  165. ErrorAlert(short stringList,short whichString)
  166.     {
  167.     Str255                    errorString;
  168.     GrafPtr                    oldPort,windowMgrPort;
  169.     short                    oldFont;
  170.     DialogTemplateHandle    errorDialogTemplate;
  171.     DialogItemListHandle    errorDialogItems;
  172.     TEHandle                aTEHandle;
  173.     Rect                    textRect;
  174.     short                    textHeight;
  175.     short                    additionalSpaceNeeded;
  176.     DialogItemPtr            okButtonItem,errorTextItem;
  177.     const StringPtr            nullStr = (StringPtr) "\p";
  178.  
  179.     GetIndString(errorString,stringList,whichString);
  180.     
  181.     errorDialogTemplate = (DialogTemplateHandle) Get1Resource('DLOG',kErrorAlertID);
  182.     HLock((Handle) errorDialogTemplate);
  183.     
  184.     errorDialogItems = (DialogItemListHandle) Get1Resource('DITL',(**errorDialogTemplate).itemsID);
  185.     HLock((Handle) errorDialogItems);
  186.     
  187.     //    Find the dialog items
  188.     
  189.     okButtonItem = (**errorDialogItems).firstItem;
  190.     errorTextItem = (DialogItemPtr) ((Ptr) okButtonItem + sizeof(DialogItem) + okButtonItem->length);
  191.     
  192.     GetPort(&oldPort);
  193.     GetWMgrPort(&windowMgrPort);
  194.     SetPort(windowMgrPort);
  195.     oldFont = qd.thePort->txFont;
  196.     TextFont(systemFont);
  197.  
  198.     // use the initial size from the 'DITL', instead of random garbage.
  199.     textRect = errorTextItem->boundsRect;
  200.     aTEHandle = TENew(&textRect,&textRect);
  201.     TESetText(&errorString[1],errorString[0],aTEHandle);
  202.     textHeight = (*aTEHandle)->lineHeight * (*aTEHandle)->nLines;
  203.     TEDispose(aTEHandle);
  204.  
  205.     additionalSpaceNeeded = textHeight - (errorTextItem->boundsRect.bottom
  206.                             - errorTextItem->boundsRect.top);
  207.  
  208.     if (additionalSpaceNeeded > 0)
  209.         {
  210.         (**errorDialogTemplate).boundsRect.bottom += additionalSpaceNeeded;
  211.         errorTextItem->boundsRect.bottom += additionalSpaceNeeded;
  212.         OffsetRect(&okButtonItem->boundsRect,0,additionalSpaceNeeded);
  213.         }
  214.         
  215.     TextFont(oldFont);
  216.     SetPort(oldPort);
  217.     
  218.     InitCursor();
  219.     ParamText(errorString,nullStr,nullStr,nullStr);
  220.  
  221.     (void) StandardAlert(kErrorAlertID);
  222.  
  223.     ReleaseResource((Handle) errorDialogTemplate);
  224.     ReleaseResource((Handle) errorDialogItems);
  225.     }
  226.  
  227.  
  228. ///////////////////////////////////////////////////////////
  229. //
  230. //    FatalErrorAlert
  231. //
  232. //    A companion to ErrorAlert which also kills the process.
  233. //
  234.  
  235. void
  236. FatalErrorAlert(short stringList,short whichString)
  237.     {
  238.     ErrorAlert(stringList,whichString);
  239.     ExitToShell();
  240.     }
  241.  
  242.  
  243. ///////////////////////////////////////////////////////////
  244. //
  245. //    StandardDialogFilter and StandardDialogFilterYD
  246. //
  247. //    These function takes care of routing events not meant
  248. //    for the dialog window to other parts of the application.
  249. //
  250. //    Use them as an alternative to passing a NIL ModalFilterProc
  251. //    to ModalDialog() and CustomGet(Put)File. Unlike the default
  252. //    filter, these routines properly processes update events
  253. //    to keep background processes running.
  254. //
  255. //    The Thread Manager, if present, is also called to yield
  256. //    control to other cooperative threads within the process.
  257. //
  258. //    Because of pascal calling conventions we need two separate
  259. //    routines, but this is minimized by sharing implementation
  260. //    in FilterProcCommon.
  261.  
  262.  
  263. ModalFilterUPP    StandardDialogFilterUPP
  264. = NewModalFilterProc(StandardDialogFilterProc);
  265.  
  266. ModalFilterYDUPP    StandardDialogFilterYDUPP
  267. = NewModalFilterYDProc(StandardDialogFilterYDProc);
  268.  
  269.  
  270. pascal Boolean
  271. StandardDialogFilterProc(DialogRef theDialog, EventRecord* anEvent, short* itemHit)
  272.     {
  273.     //    Call through common code to check for events we’d like to handle.
  274.     //    If that is unsuccessful, call through the System 7 StdFilterProc
  275.     //    to handle CR, “CMD-.” & ESC in an international-friendly manner.
  276.  
  277.     if (FilterProcCommon(theDialog, anEvent, itemHit))
  278.         return true;
  279.     else
  280.         return (StdFilterProc(theDialog, anEvent, itemHit));
  281.     }
  282.  
  283.  
  284. pascal Boolean
  285. StandardDialogFilterYDProc(DialogRef theDialog, EventRecord* anEvent, short* itemHit, void * /*unusedData*/)
  286.     {
  287.     //    We don’t call through to StdFilterProc since the
  288.     //    Standard File Package already does everything we need.
  289.  
  290.     return FilterProcCommon(theDialog, anEvent, itemHit);
  291.     }
  292.  
  293.  
  294. void
  295. PseudoClickInDialogItem(DialogRef theDialog, short itemToClick)
  296.     {
  297.     ControlRef    itemHandle;
  298.     Rect        itemBox;
  299.     long        finalTicks;
  300.     short        itemType;
  301.     
  302.     GetDialogItem(theDialog,itemToClick,&itemType, (Handle *) &itemHandle,&itemBox);
  303.  
  304.     HiliteControl( itemHandle, kControlButtonPart );
  305.     Delay(8,&finalTicks);
  306.     HiliteControl( itemHandle, 0 );
  307.     }
  308.  
  309.  
  310. Boolean
  311. ToggleCheckBox(DialogRef theDialog, short theCheckBox)
  312.     {
  313.     ControlRef    itemHandle;
  314.     Rect        itemBox;
  315.     short        itemType;
  316.     
  317.     GetDialogItem(theDialog,theCheckBox,&itemType,(Handle *) &itemHandle,&itemBox);
  318.  
  319.     if (GetControlValue(itemHandle) == 1)
  320.         {
  321.         SetControlValue(itemHandle,0);
  322.         return false;
  323.         }
  324.     else
  325.         {
  326.         SetControlValue(itemHandle,1);
  327.         return true;
  328.         }
  329.     }
  330.  
  331.  
  332. Boolean
  333. FilterProcCommon(DialogRef theDialog, EventRecord * anEvent, short * /* itemHit */)
  334.     {
  335.     switch (anEvent->what)
  336.         {
  337.         case updateEvt:
  338.         case activateEvt:
  339.             //     Update or activate for the dialog window?
  340.             if (theDialog == (DialogRef) anEvent->message)
  341.                 break;
  342.  
  343.             //    no, fall through to HandleEvent            
  344.             
  345.         case diskEvt:
  346.             HandleEvent(anEvent);
  347.             return(false);
  348.  
  349.         default:
  350.             break;        
  351.         }
  352.  
  353.     if (gHasThreadManager)        //    If we have threads, let them run!
  354.         YieldToAnyThread();
  355.  
  356.     return false;                //    We didn’t handle the event
  357.     }
  358.  
  359.  
  360. void SetDialogFontAndSize ( DialogRef theDialog, short fontNum, short fontSize ) {
  361.     GrafPtr        savePort;
  362.     TEHandle    teh = GetDialogTextEdit ( theDialog );
  363.     
  364.     GetPort ( &savePort );
  365.     SetGrafPortOfDialog ( theDialog );
  366.     
  367. //    set up the port info
  368.     TextFont ( fontNum );
  369.     TextSize ( fontSize );
  370.  
  371. //    now deal with the static & edit text issues
  372.     if ( teh != NULL ) {
  373.         FontInfo    f;
  374.         TEPtr        pText;
  375.     
  376.         GetFontInfo ( &f );
  377.         pText = *teh;
  378.         pText->txFont        = applFont;
  379.         pText->txSize        = fontSize;
  380.         pText->lineHeight    = f.ascent + f.descent + f.leading;
  381.         pText->fontAscent    = f.ascent;
  382.         }
  383.     
  384.     SetPort ( savePort );
  385.     }
  386.